﻿#include "QueryMgr.h"
#include "CenterService.h"
#include "Cache/OfflineCharacterDataMgr.h"
#include "Cache/OfflineCharacterData.h"
#include "Active/ActiveCharacter.h"
#include "Active/ActiveCharacterMgr.h"
#include "MirrorMgr/MirrorMgr.h"
#include "RelationMgr/RelationMgr.h"
#include "Team/TeamManager.h"
#include "Union/UnionMgr.h"

QueryMgr::QueryMgr()
{

}

QueryMgr::~QueryMgr()
{

}


bool QueryMgr::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		MMOLOG_FMT_ERROR("[center] QueryMgr::Init....nullptr == pMessageDispatch ");
		return false;
	}

	pMessageDispatch->registerClientHandler(EMODULE_ID_QUERY, this);
	pMessageDispatch->registerServerHandler(EMODULE_ID_QUERY, this);
	pMessageDispatch->registerDBProxyHandler(EMODULE_ID_QUERY, this);

	return true;
}

bool QueryMgr::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr != pMessageDispatch)
	{
		pMessageDispatch->unregisterClientHandler(EMODULE_ID_QUERY);
		pMessageDispatch->unregisterServerHandler(EMODULE_ID_QUERY);
		pMessageDispatch->unregisterDBProxyHandler(EMODULE_ID_QUERY);
	}

	return true;
}

void QueryMgr::onClientMessage(uint32_t actionId, RECV_PACKAGE &package, uint64_t Id)
{
	switch (actionId)
	{
	case CLIENT_TO_CENTER_CHARACTER_DETAIL_DATA:
	{
		OnCWCharacterDetailReq(Id, package);
		break;
	}
	default:
		break;
	}
}

void QueryMgr::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case LOGIC_TO_CENTER_CHARACTER_DETAIL_DATA:
	{
		OnGWCharacterDeatil(package);
		break;
	}
	default:
		break;
	}
}

void QueryMgr::onDBProxyMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case DBPROXY_PROTOCOL_QUERY_LOAD_MIRROR_DATA_CALL_BACK:
	{
		OnQueryLoadMirrorDataCallBack(package);
	}
	break;
	default:
		break;
	}
}

bool QueryMgr::OnCWCharacterDetailReq(CharIDType charID, RECV_PACKAGE &package)
{
	CWCharacterDetailReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] CWCharacterDetailReq prase failed...");
		return false;
	}

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charID);
	if (nullptr == pOnline)
	{
		LogErrFmtPrint("[center] OnCWCharacterDetailReq....nullptr == pOnline...charID:%lu ", charID);
		return false;
	}

	CharIDType dstCharID = req.charid();
	if (dstCharID == charID)
	{
		LogErrFmtPrint("[center] OnCWCharacterDetailReq....dstCharID == charID...charID:%lu ", charID);
		return false;
	}

	OfflineCharacterData *pDstOffline = nullptr;
	if (0 == dstCharID) //charid为0 时 按名字查询
	{
		if (!req.has_name())
		{
			return false;
		}
		string strName = req.name();
		pDstOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacterByName(strName.c_str());
		if (nullptr == pDstOffline)
		{
			LogErrFmtPrint("[center] OnCWCharacterDetailReq ... nullptr == pOffline, name:%s ", strName.c_str());
			return false;
		}
		dstCharID = pDstOffline->GetCharID();
	}
	else
	{
		pDstOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(dstCharID);
	}

	WCCharacterDetailRsp rsp;
	if (nullptr != pDstOffline)
	{
		//判断是否在线 如果在线直接向该角色所在的逻辑服去填充
		ActiveCharacter *pDstOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(dstCharID);
		if (nullptr != pDstOnline)
		{
			WGCharacterDetailReq logicReq;
			logicReq.set_srcid(charID);
			logicReq.set_dstid(dstCharID);
			logicReq.set_type(req.type());
			g_GetCenterService()->SendDataToLogicByCharID(dstCharID, EMODULE_ID_QUERY, CENTER_TO_LOGIC_CHARACTER_DETAIL_DATA, &logicReq);
			return true;
		}

		//查找一下对方是否存在镜像缓存中
		MirrorRole* pMirrorRole = g_GetMirrorMgr()->Get(dstCharID);
		if (nullptr == pMirrorRole)
		{
			//如果不存在那么开始加载镜像数据
			QueryLoadMirrorDataCallBack callBack;
			callBack.set_srcid(charID);
			callBack.set_dstid(dstCharID);
			callBack.set_type(req.type());
			//交给系统管理器去负责加载镜像数据
			g_GetMirrorMgr()->LoadCharacterMirrorData(dstCharID, EMODULE_ID_QUERY, DBPROXY_PROTOCOL_QUERY_LOAD_MIRROR_DATA_CALL_BACK, &callBack);
		}
		else
		{
			OnQueryCharacterDetail(charID, dstCharID, req.type());
		}
	}
	else
	{
		//玩家不存在
		rsp.set_ret(RET_CHAT_QUREY_CHAR_NOT_EXITS);
		g_GetCenterService()->SendDataToClient(charID, EMODULE_ID_QUERY, CENTER_TO_CLIENT_CHARACTER_DETAIL_DATA, &rsp);
	}
	return true;
}

bool QueryMgr::OnQueryLoadMirrorDataCallBack(RECV_PACKAGE &package)
{
	QueryLoadMirrorDataCallBack rsp;
	if (!rsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[center] QueryLoadMirrorDataCallBack return but parse failed....");
		return false;
	}

	CharIDType charId = rsp.srcid();
	CharIDType dstId = rsp.dstid();
	uint32_t type = rsp.type();

	OnQueryCharacterDetail(charId, dstId, type);

	return true;

}

bool QueryMgr::OnQueryCharacterDetail(CharIDType srcId, CharIDType dstId, uint32_t type)
{
	WCCharacterDetailRsp rsp;
	rsp.set_ret(RET_SUCCESS);
	rsp.set_type(type);

	for (uint32_t i = CQTE_ROLE_TYPE; i <= CQTE_PET_TYPE; i++)
	{
		if ((type >> i) & 0x0001)
		{
			switch (i)
			{
			case CQTE_ROLE_TYPE:
			{
				QueryCharacterdDetailInfo(srcId, dstId, rsp);
			}
			break;
			case CQTE_PET_TYPE:
			{
				QueryCharacterdPetInfo(srcId, dstId, rsp);
			}
			break;
			default:
				break;
			}
		}
	}

	g_GetCenterService()->SendDataToClient(srcId, EMODULE_ID_QUERY, CENTER_TO_CLIENT_CHARACTER_DETAIL_DATA, &rsp);
	return true;
}

bool QueryMgr::QueryCharacterdDetailInfo(CharIDType srcId, CharIDType dstId, WCCharacterDetailRsp& rsp)
{
	OfflineCharacterData* pDstOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(dstId);
	if (nullptr == pDstOffline)
	{
		MMOLOG_FMT_ERROR("[center] QueryMgr::QueryCharacterdDetailInfo but OfflineCharacterData is null, dstId:%llu....", dstId);
		return false;
	}

	MirrorRole* pMirrorRole = g_GetMirrorMgr()->Get(dstId);
	if (nullptr == pMirrorRole)
	{
		MMOLOG_FMT_ERROR("[center] QueryMgr::QueryCharacterdDetailInfo but pMirrorRole==nullptr srcId:%ld, dstId:%llu....", srcId, dstId);
		return false;
	}

	CharacterMirrorData* pMirrorData = pMirrorRole->Get();
	if (nullptr == pMirrorData)
	{
		MMOLOG_FMT_ERROR("[center] QueryMgr::QueryCharacterdDetailInfo but pMirrorData==nullptr srcId:%ld, dstId:%llu....", srcId, dstId);
		return false;
	}

	const CharacterDBBaseInfo& baseInfo = pMirrorData->baseinfo();
	const CharacterDBEquipData& equipData = pMirrorData->equips();
	const CharacterDBExtendData& extendData = pMirrorData->attr();

	QueryCharacterDetailInfo* detailInfo = rsp.mutable_characterinfo();
	detailInfo->set_fightpower(pDstOffline->GetFight());
	detailInfo->set_name(pDstOffline->GetCharName());
	detailInfo->set_level(pDstOffline->GetLevel());
	detailInfo->set_id(dstId);
	detailInfo->set_prof(pDstOffline->GetProf());
	detailInfo->set_title(baseInfo.usetitle());
	detailInfo->set_official(pDstOffline->GetOfficial());
	detailInfo->set_knight(pDstOffline->GetKnight());
	detailInfo->set_contribute(pDstOffline->GetContribute());
	detailInfo->set_prestige(pDstOffline->GetPrestige());
	detailInfo->set_camp(pDstOffline->GetCampID());
	detailInfo->set_sex(pDstOffline->GetSex());
	CUnion *pUnion = g_GetUnionMgr()->GetCharUnion(dstId);
	if (nullptr != pUnion)
	{
		detailInfo->set_guildname(pUnion->Name());
	}
	detailInfo->set_hp(baseInfo.hp());
	detailInfo->set_maxhp(extendData.attr_detail().max_hp());
	detailInfo->set_mp(baseInfo.mp());
	detailInfo->set_maxmp(extendData.attr_detail().max_mp());
	detailInfo->set_exp(baseInfo.exp());
	detailInfo->set_isfriend(g_GetRelationMgr()->IsFriendRelation(srcId, dstId));
	detailInfo->set_power(baseInfo.power());
	detailInfo->set_intelligence(baseInfo.intelligence());
	detailInfo->set_agility(baseInfo.agility());
	detailInfo->set_physique(baseInfo.physique());
	detailInfo->set_endurance(baseInfo.endurance());
	detailInfo->set_precision(baseInfo.precision());
	detailInfo->set_ap(extendData.attr_detail().ap());
	detailInfo->set_mat(extendData.attr_detail().mat());
	detailInfo->set_dp(extendData.attr_detail().dp());
	detailInfo->set_mdp(extendData.attr_detail().mdp());
	detailInfo->set_phyhit(extendData.attr_detail().phyhit());
	detailInfo->set_phydodge(extendData.attr_detail().phydodge());
	detailInfo->set_phycrit(extendData.attr_detail().phycrit());
	detailInfo->set_magcrit(extendData.attr_detail().magcrit());
	detailInfo->set_phytoughness(extendData.attr_detail().phytoughness());
	detailInfo->set_magtoughness(extendData.attr_detail().magtoughness());
	detailInfo->set_phycritmul(extendData.attr_detail().phycritmul());
	detailInfo->set_magcritmul(extendData.attr_detail().magcritmul());
	detailInfo->set_fireatt(extendData.attr_detail().fireatt());
	detailInfo->set_firedef(extendData.attr_detail().firedef());
	detailInfo->set_icedatt(extendData.attr_detail().icedatt());
	detailInfo->set_iceddef(extendData.attr_detail().iceddef());
	detailInfo->set_windatt(extendData.attr_detail().windatt());
	detailInfo->set_winddef(extendData.attr_detail().winddef());
	detailInfo->set_solatt(extendData.attr_detail().solatt());
	detailInfo->set_soldef(extendData.attr_detail().soldef());
	detailInfo->set_rayatt(extendData.attr_detail().rayatt());
	detailInfo->set_raydef(extendData.attr_detail().raydef());
	detailInfo->set_poisonatt(extendData.attr_detail().poisonatt());
	detailInfo->set_poisondef(extendData.attr_detail().poisondef());
	detailInfo->set_phycritextra(extendData.attr_detail().phycritextra());
	detailInfo->set_phycritreduce(extendData.attr_detail().phycritreduce());
	detailInfo->set_phyextradamage(extendData.attr_detail().phyextradamage());
	detailInfo->set_phyreducedamage(extendData.attr_detail().phyreducedamage());
	detailInfo->set_magcritextra(extendData.attr_detail().magcritextra());
	detailInfo->set_magcritreduce(extendData.attr_detail().magcritreduce());
	detailInfo->set_magextradamage(extendData.attr_detail().magextradamage());
	detailInfo->set_magreducedamage(extendData.attr_detail().magreducedamage());
	detailInfo->set_controldawn(extendData.attr_detail().controldawn());
	detailInfo->set_persistdown(extendData.attr_detail().persistdown());
	detailInfo->set_weakdown(extendData.attr_detail().weakdown());
	detailInfo->set_displacedown(extendData.attr_detail().displacedown());
	detailInfo->set_silencedown(extendData.attr_detail().silencedown());
	detailInfo->set_controlup(extendData.attr_detail().controlup());
	detailInfo->set_persistup(extendData.attr_detail().persistup());
	detailInfo->set_weakup(extendData.attr_detail().weakup());
	detailInfo->set_displaceup(extendData.attr_detail().displaceup());
	detailInfo->set_silenceup(extendData.attr_detail().silenceup());
	detailInfo->set_dw_rune_id(equipData.dw_rune_id());
	detailInfo->set_yk_rune_id(equipData.yk_rune_id());
	detailInfo->mutable_facade()->CopyFrom(pDstOffline->GetFacade());
	detailInfo->mutable_equips()->CopyFrom(equipData.equip());
	detailInfo->mutable_slots()->CopyFrom(equipData.equip_slot());
	detailInfo->set_isonline(false);
	detailInfo->set_magdodge(extendData.attr_detail().magdodge());
	detailInfo->set_teamid(g_GetTeamMgr()->GetTeamId(dstId));
	detailInfo->set_maghit(extendData.attr_detail().maghit());
	return true;
}

bool QueryMgr::QueryCharacterdPetInfo(CharIDType srcId, CharIDType dstId, WCCharacterDetailRsp& rsp)
{
	MirrorRole* pMirrorRole = g_GetMirrorMgr()->Get(dstId);
	if (nullptr == pMirrorRole)
	{
		MMOLOG_FMT_ERROR("[center] QueryMgr::QueryCharacterdPetInfo can not find mirror data srcId:%ld, dstId:%llu....", srcId, dstId);
		return false;
	}

	CharacterMirrorData* pMirrorData = pMirrorRole->Get();
	if (nullptr == pMirrorData)
	{
		MMOLOG_FMT_ERROR("[center] QueryMgr::QueryCharacterdPetInfo but pMirrorData==nullptr srcId:%ld, dstId:%llu....", srcId, dstId);
		return false;
	}

	const CharacterPetData& petInfo = pMirrorData->petdata();
	for (int32_t i = 0; i < petInfo.petinfo_size(); i++)
	{
		if (petInfo.petinfo(i).playerpetid() == petInfo.curfightpetid())
		{
			QueryPetDetailInfo* detailInfo = rsp.mutable_petinfo();
			detailInfo->set_playerpetid(petInfo.petinfo(i).playerpetid());
			detailInfo->set_configpetid(petInfo.petinfo(i).configpetid());
			detailInfo->set_eatvalue(petInfo.petinfo(i).eatvalue());
			detailInfo->mutable_learnskills()->CopyFrom(petInfo.petinfo(i).learnskills());
			return true;
		}
	}

	return false;
}

bool QueryMgr::OnGWCharacterDeatil(RECV_PACKAGE &package)
{
	GWCharacterDetailRsp rsp;

	if (!rsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] QueryMgr::OnGWCharacterDeatil GWCharacterDetailRsp parse failed...");
		return false;
	}

	CharIDType srcId = rsp.srcid();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(srcId);
	if (nullptr == pOnline)
	{
		LogErrFmtPrint("[center] OnGWCharacterDeatil....nullptr == pOnline...charID:%lu ", srcId);
		return false;
	}

	WCCharacterDetailRsp* toClient = rsp.mutable_rsp();
	if (toClient->has_characterinfo())
	{
		//填充好友信息
		CharIDType dstId = toClient->characterinfo().id();
		toClient->mutable_characterinfo()->set_isfriend(g_GetRelationMgr()->IsFriendRelation(srcId, dstId));
	}

	g_GetCenterService()->SendDataToClient(srcId, EMODULE_ID_QUERY, CENTER_TO_CLIENT_CHARACTER_DETAIL_DATA, toClient);

	return true;
}